package com.tbit.uqbike.service.base.impl;

import com.alibaba.fastjson.JSONObject;
import com.tbit.uqbike.constant.OperaPswConstant;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.service.base.RedisService;
import com.tbit.uqbike.service.base.TokenService;
import com.tbit.uqbike.service.business.AccountService;
import com.tbit.uqbike.webmanager.controller.interceptor.HttpHeadName;
import com.tbit.uqbike.webmanager.util.LogUtil;
import com.tbit.uqbike.webmanager.util.ServletUtils;
import com.tbit.uqbike.webmanager.util.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author MyWin E-mail:335918956@qq.com
 * @version 1.0
 * @createTime 2019-12-05 17:43
 */
@Slf4j
@Service
public class TokenServiceImpl implements TokenService {
    // token前缀
    private static final String TOKEN2USER_PREFIX = "token.uq";
    private static final String USER2TOKEN_PREFIX = "user.uq";
    @Autowired
    private RedisService redisService;
    @Autowired
    private AccountService accountService;
    @Autowired
    private RedisUtil redisUtil;

    private String getUser2TokenKey(Integer type, Integer id) {
        return String.format("%s.%d.%d", USER2TOKEN_PREFIX, type, id);
    }

    public String getUser2TokenKey(Integer id) {
        return String.format("%s.%d", USER2TOKEN_PREFIX, id);
    }

    private String getToken2UserKey(String token) {
        return String.format("%s.%s", TOKEN2USER_PREFIX, token);
    }

    @Override
    public LoginInfo getLoginInfo(String token) {
        String str = redisService.get(getToken2UserKey(token));
        if (!StringUtils.isEmpty(str)) {
            try {
                LoginInfo loginInfo = JSONObject.parseObject(str, LoginInfo.class);
                if (loginInfo.roleIsAdmin()) {
                    //管理员刷新缓存时间
                    redisService.add(getUser2TokenKey(loginInfo.accountUserId), token, OperaPswConstant.TOKEN_EXPIRE_TIME);
                    redisService.add(getToken2UserKey(token), str, OperaPswConstant.TOKEN_EXPIRE_TIME);
                } else {
                    //兼容旧登录账号的新增字段为空导致的空指针的情况
                    if (loginInfo.getBrandId() == null) {
                        Integer brandId = accountService.getBrandIdByAccountId(loginInfo.getId());
                        log.info("账户:{}，获取的品牌id为空，初始化品牌id:{}", str, brandId);
                        loginInfo.setBrandId(brandId);
                        str = JSONObject.toJSONString(loginInfo);
                        Long expire = redisUtil.getExpire(getToken2UserKey(token), TimeUnit.SECONDS);
                        log.info("账户:{}，获取的过期时间:{}秒", str, expire);
                        if (expire == null) {
                            expire = OperaPswConstant.TOKEN_EXPIRE_TIME.longValue();
                        }
                        redisService.add(getUser2TokenKey(loginInfo.accountUserId), token, expire.intValue());
                        redisService.add(getToken2UserKey(token), str, expire.intValue());
                        log.info("账户:{}，token：{}，刷新缓存:{}秒", str, token, expire);
                    }
                }
                return loginInfo;
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                LogUtil.warn(e.getMessage());
            }
        }
        return null;
    }

    @Override
    public LoginInfo getLoginInfo() {
        return getLoginInfo(ServletUtils.getRequest().getHeader(HttpHeadName.REQUEST_ATTR_NAME_TOKEN));
    }

    @Override
    public String initToken(LoginInfo info) {
        String key = getUser2TokenKey(info.accountUserId);
        String token = UUID.randomUUID().toString();
        // 获取老的token，如果存在就获取回来清空历史，覆盖新的
        String existToken = redisService.get(key);
        if (!StringUtils.isEmpty(existToken)) {
            if (OperaPswConstant.SINGLE_LOGIN_FLAG) {
                // 清除token
                redisService.del(getToken2UserKey(existToken));
            }
        }
        redisService.add(key, token, OperaPswConstant.TOKEN_EXPIRE_TIME);
        redisService.add(getToken2UserKey(token), JSONObject.toJSONString(info), OperaPswConstant.TOKEN_EXPIRE_TIME);
        return token;
    }

    @Override
    public void destroyToken(LoginInfo info) {
        String token2UserKey = getToken2UserKey(redisService.get(getUser2TokenKey(info.accountUserId)));
        String user = redisService.get(token2UserKey);
        if (null != user) {
            log.info("账户:{}，销毁token:{}", JSONObject.toJSONString(user), token2UserKey);
            redisService.del(token2UserKey);
        }
    }

    @Override
    public void refreshToken(Integer second) {
        String token = ServletUtils.getRequest().getHeader(HttpHeadName.REQUEST_ATTR_NAME_TOKEN);
        String str = redisService.get(getToken2UserKey(token));
        LoginInfo loginInfo = JSONObject.parseObject(str, LoginInfo.class);
        log.info("账户:{}，刷新token:{}，有效期{}秒", str, token, second);
        //刷新缓存时间
        redisService.add(getUser2TokenKey(loginInfo.accountUserId), token, second);
        redisService.add(getToken2UserKey(token), str, second);
    }
}
